/*
# Copyright (c) 2020 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
*/

#include <stdio.h>
#include <unistd.h>
#include <stddef.h>
#include "ohos_init.h"
#include "cmsis_os2.h"

#include "hi_io.h"
#include "hi_gpio.h"
#include "hi_time.h"
#include "hi_i2c.h"
#include "max30102_hello.h"

#define IOT_SUCCESS 0
#define BIT_MOVE_16 16
#define BIT_MOVE_8 8
enum MyData {
    DATA_LEN1 = 1,
    DATA_LEN2,
    DATA_LEN3,
    DATA_LEN4,
    DATA_LEN5,
    DATA_LEN6,
};
enum MyDataBit {
    BIT_0,
    BIT_1,
    BIT_2,
    BIT_3,
    BIT_4,
    BIT_5,
    BIT_6,
};

unsigned short MAX_Cmd(unsigned short regAddr)
{
    hi_i2c_idx id = MAX_I2C_IDX;
    unsigned char buffer[] = {regAddr};
    hi_i2c_data i2cData;
    i2cData.receive_buf = NULL;
    i2cData.receive_len = 0;
    i2cData.send_buf = buffer;
    i2cData.send_len = sizeof(buffer) / sizeof(buffer[0]);
    return hi_i2c_write((hi_i2c_idx)id, MAX30102_WR_address, &i2cData);
}

uint32_t MAX_Write_Data(unsigned short regAddr, unsigned short *data, unsigned int dataLen)
{
    hi_i2c_idx id = MAX_I2C_IDX;
    unsigned char buffer[] = {regAddr, data[0]};
    hi_i2c_data i2cData;
    i2cData.receive_buf = NULL;
    i2cData.receive_len = dataLen;
    i2cData.send_buf = buffer;
    i2cData.send_len = sizeof(buffer) / sizeof(buffer[0]);
    return hi_i2c_write((hi_i2c_idx)id, I2C_WRITE_ADDR, &i2cData);
}

uint32_t MAX_Read_Data(unsigned short regAddr, unsigned short *data, unsigned int dataLen)
{
    hi_i2c_idx id = MAX_I2C_IDX;
    hi_i2c_data i2cData;
    i2cData.send_buf = NULL;
    i2cData.send_len = 0;
    i2cData.receive_buf = (unsigned char *)data;
    i2cData.receive_len = dataLen;
    MAX_Cmd(regAddr);
    return hi_i2c_read((hi_i2c_idx)id, I2C_READ_ADDR, &i2cData);
}

void max_reset(void)
{
    unsigned short add = 0x40;
    MAX_Write_Data(MODE_CONFIG, &add, DATA_LEN1);
}

void max_init(void)
{
    unsigned short max30102_info = 0;
    printf("\r\n come in MAX30102 init\r\n");
    max_reset();
    MAX_Read_Data(PART_ID, &max30102_info, DATA_LEN1);
    printf("PART_ID = %d \n", max30102_info);
    if (max30102_info == 0) {
        printf("\r\n MAX30102 init Faild \r\n");
       // return;
    }
    printf("\r\n MAX30102 init Successful \r\n");
    
    unsigned short msg[]={0xc0,0x00,0x0f,0x03,0x27,0x24,0x7f};
    MAX_Write_Data(INTR_ENABLE_1, &msg[0], DATA_LEN1); // INTR setting
    MAX_Write_Data(INTR_ENABLE_2, &msg[1], DATA_LEN1);
    MAX_Write_Data(FIFO_WR_PTR, &msg[1], DATA_LEN1); // FIFO_WR_PTR[4:0]
    MAX_Write_Data(OVF_COUNTER, &msg[1], DATA_LEN1); // OVF_COUNTER[4:0]
    MAX_Write_Data(FIFO_RD_PTR, &msg[1], DATA_LEN1); // FIFO_RD_PTR[4:0]
    MAX_Write_Data(FIFO_CONFIG, &msg[2], DATA_LEN1); // sample avg = 1, fifo rollover=false, fifo almost full = 17
    MAX_Write_Data(MODE_CONFIG, &msg[3], DATA_LEN1); // 0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
    MAX_Write_Data(SPO2_CONFIG, &msg[4], DATA_LEN1); // ADC range = 4096nA, sample rate (100 Hz)
    MAX_Write_Data(LED1_PA, &msg[5], DATA_LEN1);
    MAX_Write_Data(LED2_PA, &msg[5], DATA_LEN1);
    MAX_Write_Data(PILOT_PA, &msg[6], DATA_LEN1);
}

void max_Data(unsigned short *RED_channel_data, unsigned short *IR_channel_data)
{
    unsigned short buff[BIT_6]; // LSB
    int res;
    res = MAX_Read_Data(FIFO_DATA, buff, DATA_LEN6);
    if (res == IOT_SUCCESS) {
        *RED_channel_data = ((buff[BIT_0] << BIT_MOVE_16) | (buff[BIT_1] << BIT_MOVE_8) | ((buff[BIT_2]) & 0x03ffff));
        *IR_channel_data = ((buff[BIT_3] << BIT_MOVE_16) | (buff[BIT_4] << BIT_MOVE_8) | ((buff[BIT_5]) & 0x03ffff));
    }
}

void max_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led)
{
    uint32_t un_temp;
    unsigned short uch_temp;
    char ach_i2c_data[BIT_6];
    *pun_red_led = 0;
    *pun_ir_led = 0;

    // read and clear status register
    MAX_Read_Data(INTR_STATUS_1, &uch_temp, DATA_LEN1);
    MAX_Read_Data(INTR_STATUS_2, &uch_temp, DATA_LEN1);

    MAX_Read_Data(FIFO_DATA, (unsigned short *)ach_i2c_data, DATA_LEN6);

    un_temp = (unsigned short)ach_i2c_data[BIT_0];
    un_temp <<= BIT_MOVE_16;
    *pun_red_led += un_temp;
    un_temp = (unsigned short)ach_i2c_data[BIT_1];
    un_temp <<= BIT_MOVE_8;
    *pun_red_led += un_temp;
    un_temp = (unsigned short)ach_i2c_data[BIT_2];
    *pun_red_led += un_temp;

    un_temp = (unsigned short)ach_i2c_data[BIT_3];
    un_temp <<= BIT_MOVE_16;
    *pun_ir_led += un_temp;
    un_temp = (unsigned short)ach_i2c_data[BIT_4];
    un_temp <<= BIT_MOVE_8;
    *pun_ir_led += un_temp;
    un_temp = (unsigned short)ach_i2c_data[BIT_5];
    *pun_ir_led += un_temp;
    *pun_red_led &= 0x03FFFF; // Mask MSB [23:18]
    *pun_ir_led &= 0x03FFFF;  // Mask MSB [23:18]
}
